#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

#define COUNT 5

typedef struct {
    int value;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
} sema_t;  // 信号量

sema_t last_is_ping_sema, last_is_pong_sema;  // 只需两个信号量即可满足互斥和同步

void sema_init(sema_t *sema, int value) {
    sema->value = value;
    pthread_mutex_init(&sema->mutex, NULL);
    pthread_cond_init(&sema->cond, NULL);
}

void sema_wait(sema_t *sema) {
    pthread_mutex_lock(&sema->mutex);
    while (sema->value <= 0)
        pthread_cond_wait(&sema->cond, &sema->mutex);
    sema->value--;
    pthread_mutex_unlock(&sema->mutex);
}

void sema_signal(sema_t *sema) {
    pthread_mutex_lock(&sema->mutex);
    ++sema->value;
    pthread_cond_signal(&sema->cond);
    pthread_mutex_unlock(&sema->mutex);
}

void *ping(void *arg) {
    int i;
    for(i = 0; i < COUNT; i ++) {
        sema_wait(&last_is_pong_sema);
        printf("ping\n");
        sema_signal(&last_is_ping_sema);
    }
    return NULL;
}

void *pong(void *arg) {
    int i;
    for(i = 0; i < COUNT; i ++) {
        sema_wait(&last_is_ping_sema);
        printf("pong\n");
        sema_signal(&last_is_pong_sema);
    }
    return NULL;
}

int main() {
    pthread_t ping_tid, pong_tid;

    sema_init(&last_is_ping_sema, 0);  // 初始化为0，表示上一个不是ping
    sema_init(&last_is_pong_sema, 1);  // 初始化为1，表示上一个是pong，保证了第一个是ping

    pthread_create(&ping_tid, NULL, ping, NULL);
    pthread_create(&pong_tid, NULL, pong, NULL);

    pthread_join(ping_tid, NULL);
    pthread_join(pong_tid, NULL);

    return 0;
}